package com.quick.develop.flowable.framework.convert.definition;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.quick.develop.flowable.domain.vo.rule.BpmRuleReqVO;
import com.quick.develop.flowable.domain.vo.rule.BpmRuleRespVO;
import com.quick.develop.framework.utils.collection.CollectionUtils;
import com.quick.develop.flowable.domain.rule.BpmProcessRule;
import org.flowable.bpmn.model.CallActivity;
import org.flowable.bpmn.model.UserTask;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author junyuan.liu
 * @description
 * @date 2022/5/18 16:57
 */

@Mapper
public interface BpmProcessRuleConvert {
    BpmProcessRuleConvert INSTANCE = Mappers.getMapper(BpmProcessRuleConvert.class);

    default List<BpmRuleRespVO> convertList(List<UserTask> tasks,
                                            List<CallActivity> activities,
                                            List<BpmProcessRule> rules,
                                            BpmRuleReqVO reqVo) {
        Map<String, BpmProcessRule> ruleMap = CollectionUtils.convertMap(rules, BpmProcessRule::getNodeCode);
        List<BpmRuleRespVO> list1 = CollectionUtils.convertList(tasks, task -> {
            BpmRuleRespVO respVO = convert(ruleMap.get(task.getId()));
            return convert(task, respVO, reqVo);
        });
        List<BpmRuleRespVO> list2 = CollectionUtils.convertList(activities, at -> {
            BpmRuleRespVO respVO = convert(ruleMap.get(at.getId()));
            return convert(at, respVO, reqVo);
        });

        return Stream.concat(list1.stream(), list2.stream()).collect(Collectors.toList());
    }

    default BpmRuleRespVO convert(UserTask task, BpmRuleRespVO respVO, BpmRuleReqVO reqVo) {
        if (ObjectUtil.isEmpty(respVO)) {
            respVO = new BpmRuleRespVO();
        }
        respVO.setNodeCode(task.getId());
        respVO.setNodeName(task.getName());
        respVO.setModelId(reqVo.getModelId());
        respVO.setModelKey(reqVo.getModelKey());
        respVO.setProcessDefinitionId(reqVo.getProcessDefinitionId());
        respVO.setDeploymentId(reqVo.getDeploymentId());
        respVO.setIsMulti(task.hasMultiInstanceLoopCharacteristics());
        if (CollUtil.isEmpty(respVO.getBtnEvents())) {
            respVO.setBtnEvents(Collections.emptyList());
        }
        return respVO;
    }

    default BpmRuleRespVO convert(CallActivity activity, BpmRuleRespVO respVO, BpmRuleReqVO reqVo) {
        if (ObjectUtil.isEmpty(respVO)) {
            respVO = new BpmRuleRespVO();
        }
        respVO.setNodeCode(activity.getId());
        respVO.setNodeName(activity.getName());
        respVO.setModelId(reqVo.getModelId());
        respVO.setModelKey(reqVo.getModelKey());
        respVO.setProcessDefinitionId(reqVo.getProcessDefinitionId());
        respVO.setDeploymentId(reqVo.getDeploymentId());
        respVO.setIsMulti(activity.hasMultiInstanceLoopCharacteristics());
        if (CollUtil.isEmpty(respVO.getBtnEvents())) {
            respVO.setBtnEvents(Collections.emptyList());
        }
        return respVO;
    }

    BpmRuleRespVO convert(BpmProcessRule bean);

    default BpmRuleRespVO convertVo(BpmProcessRule rule, List<HistoricTaskInstance> hisTaskList) {
        BpmRuleRespVO respVO = convert(rule);
        List<String> backNodeCode = rule.getBackNodeCode();
        if (!CollUtil.isEmpty(backNodeCode) && CollUtil.isNotEmpty(hisTaskList)) {
            /*List<BpmRuleRespVO.BackNode> list = new ArrayList<>();
            for (int i = 0; i < backNodeCode.size(); i++) {
                BpmRuleRespVO.BackNode backNode = new BpmRuleRespVO.BackNode();
                String nc = backNodeCode.get(i);
                backNode.setNodeCode(nc);
                if (Objects.nonNull(rule.getBackNodeName()) && rule.getBackNodeName().size() > i) {
                    backNode.setNodeName(rule.getBackNodeName().get(i));
                }else {
                    backNode.setNodeName(nc);
                }
                list.add(backNode);
            }
            respVO.setBackNodeList(list);*/
            respVO.setBackNodeList(getBackNode(hisTaskList, backNodeCode, rule.getBackNodeName()));
        }

        return respVO;
    }

    default List<BpmRuleRespVO.BackNode> getBackNode(List<HistoricTaskInstance> hisTaskList, List<String> backNodeCode, List<String> backNodeName) {
        List<BpmRuleRespVO.BackNode> list = new ArrayList<>();
        hisTaskList.forEach(t -> {
            String key = t.getTaskDefinitionKey();
            if (Objects.isNull(CollectionUtils.findFirst(list, e -> e.getNodeCode().equals(key))) &&
                    backNodeCode.contains(key)) {
                int i = backNodeCode.indexOf(key);
                BpmRuleRespVO.BackNode backNode = new BpmRuleRespVO.BackNode();
                backNode.setNodeCode(key);
                backNode.setNodeName(backNodeName.get(i));
                list.add(backNode);
            }
        });
        return list;
    }

}
